/*
 * Copyright (C) 2023 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "hi_io.h"
#include "iot_gpio.h"
#include "iot_errno.h"

#include "net_config.h"
#include "pzcar_i2c_ctrl.h"
#include "pzcar_wheel_ctrl.h"
#include "pzcar_button_ctrl.h"

extern char* eCm_String[];
extern char* eSt_String[];
extern PzCarInfo g_carInfo;

// WiFi_IoT
//#define BTN_A  HI_IO_NAME_GPIO_7    // SWITCH1
//#define BTN_B  HI_IO_NAME_GPIO_5    // SWITCH2

//OpenBrother
//#define BTN_A  HI_IO_NAME_GPIO_10
//#define BTN_B  HI_IO_NAME_GPIO_2

unsigned char page_curr = 0;
  signed char item_curr = 0;

// page_0 default eMode_Max[4] items: CarMode:[Auto/Track/AudCmd/NetCtrl]
// page_1 default 2 items:[NetServer/NetConfig]
unsigned char page_item_def_cnt[] = { eMode_Max, Net_MODE_NET_MAX };

//////////////////////////////////////////////
static int btn_a_st = BTN_INVALID;
static int btn_b_st = BTN_INVALID;

static void BtnA_Press(void)
{
    btn_a_st = BTN_PRESS;
}
static void BtnA_Release(void)
{
    if (btn_a_st == BTN_PRESS) {
        btn_a_st = BTN_RELEASE;
        
        g_carInfo.e_ST = eSt_Stop;
        //printf("BtnA_Release: [i]page_curr[%d], item_curr[%d]\n", page_curr, item_curr);
        switch (page_curr) {
            case 0:   // display Page_0_Mode[0]
                item_curr = (item_curr+1)%page_item_def_cnt[page_curr];
                break;
            case 1:   // display Page_1_NetCtrl[2]
                item_curr = (item_curr+1)%page_item_def_cnt[page_curr];
                break;
            case 2:   // go back to display Page_0_Mode[0]
            case 3:
                page_curr = 0;
                item_curr = 0;
                break;
            default:
                break;
        }
        //printf("BtnA_Release: [o]page_curr[%d], item_curr[%d]\n", page_curr, item_curr);
    }
    IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_10,
                           BTN_INT_TYPE,
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                           BtnA_Press,
                           NULL);
}
static void BtnB_Press(void)
{
    btn_b_st = BTN_PRESS;
}
static void BtnB_Release(void)
{
    if (btn_b_st == BTN_PRESS) {
        btn_b_st = BTN_RELEASE;
        
        //printf("BtnB_Release: [i]page_curr[%d], item_curr[%d]\n", page_curr, item_curr);
        switch (page_curr) {
        case 0:  //on Menu[0], select item_curr as CarMode
            if (item_curr == eMode_NetCtrl) {
                page_curr = 1;  // display Page_1_NetCtrl[2]: NetCtrl select page
                //g_carInfo.e_CM = eMode_NetCtrl;
            } else {
                g_carInfo.e_CM = item_curr%eMode_Max;
                page_curr = 2;  // display Page_2_Status[]: Auto/Track/AudCmd status page
            }
            item_curr = 0;
            break;
        case 1:  //on Page_1_NetCtrl[2], select item_curr as NetCtrl Mode
            g_carInfo.e_CM = eMode_NetCtrl;
            if (item_curr == 0) {         // Net_MODE_NET_SERVER
                page_curr = 2;            // display Page_2_Status[]: NetCtrl status page
                g_carInfo.e_NetMode = Net_MODE_NET_SERVER;
            } else if (item_curr == 1) {  // Net_MODE_NET_CONFIG
                page_curr = 3;            // display Page_3_NetConfig[]
                g_carInfo.e_NetMode = Net_MODE_NET_CONFIG;
                //g_carInfo.e_NetST = Net_ST_Config;  //Going into NetConfig Mode
            }
            item_curr = 0;
            break;
        case 2:  //on Page_2_Status[], switch CarState: forward/backward....
            if (g_carInfo.e_CM == eMode_NetCtrl) {
                item_curr = (item_curr+1)%3;
            } else {
                g_carInfo.e_ST = (g_carInfo.e_ST+1)%eSt_Max;
            }
            break;
        case 3:  //on Page_3_NetConfig[]
            //g_carInfo.e_ST = (g_carInfo.e_ST+1)%eSt_Max;
            item_curr = (item_curr+1)%3;
            break;
        default:
            break;
        }
        //printf("BtnB_Release: [o]page_curr[%d], item_curr[%d]\n", page_curr, item_curr);
    }
    IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_2,
                           BTN_INT_TYPE,
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                           BtnB_Press,
                           NULL);
}

void ButtonIoInit(void)
{
    // BUTTON_A inited with a BTN_INT_TYPE trigger interrupt
    IoTGpioInit(HI_IO_NAME_GPIO_10);
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_GPIO);
    IoTGpioSetDir(HI_IO_NAME_GPIO_10, IOT_GPIO_DIR_IN);
    hi_io_set_pull(HI_IO_NAME_GPIO_10, HI_IO_PULL_UP);
    IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_10,
                           BTN_INT_TYPE,
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                           BtnA_Press,
                           NULL);

    // BUTTON_B inited with a BTN_INT_TYPE trigger interrupt
    IoTGpioInit(HI_IO_NAME_GPIO_2);
    hi_io_set_func(HI_IO_NAME_GPIO_2, HI_IO_FUNC_GPIO_10_GPIO);
    IoTGpioSetDir(HI_IO_NAME_GPIO_2, IOT_GPIO_DIR_IN);
    hi_io_set_pull(HI_IO_NAME_GPIO_2, HI_IO_PULL_UP);
    IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_2,
                           BTN_INT_TYPE,
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                           BtnB_Press,
                           NULL);
}

void ButtonIntAlter(void)
{
    if (btn_a_st == BTN_PRESS) {
        IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_10,
                               BTN_INT_TYPE,
                               IOT_GPIO_EDGE_RISE_LEVEL_HIGH,
                               BtnA_Release,
                               NULL);
    }
    if (btn_b_st == BTN_PRESS) {
        IoTGpioRegisterIsrFunc(HI_IO_NAME_GPIO_2,
                               BTN_INT_TYPE,
                               IOT_GPIO_EDGE_RISE_LEVEL_HIGH,
                               BtnB_Release,
                               NULL);
    }
}

void ButtonTask(void)
{
    ButtonIoInit();
    while (1) {
        usleep(50*1000);
        ButtonIntAlter();
    }
}

osThreadId_t ButtonTaskEntry(void)
{
    //osPriorityAboveNormal[32], osPriorityNormal[24]
    //{.name, .attr_bits, .cb_mem, .cb_size, .stack_mem, .stack_size, .priority, .tz_module, .reserved}
    osThreadAttr_t attr = {"ButtonTask", 0, NULL, 0, NULL, 1024*2, 24, 0, 0};
    osThreadId_t taskId = osThreadNew(ButtonTask, NULL, &attr);
    if (taskId == NULL) {
        printf("%s: Failed to create %s!\n", __func__, attr.name);
        return NULL;
    }
    return taskId;
}